//Copyright (c) Microsoft Corporation.  All rights reserved.

using System;
using System.Collections.Generic;
using System.Text;

namespace Eas.WebCrawler.PlugIns.Histories {
    /// <summary>An implementation of <see cref="Eas.WebCrawler.Interfaces.CompletedRequestHistory"/> that stores completed requests in a file so that they will not be processed in future runs.</summary>
    public class FileBasedRequestHistory : Eas.WebCrawler.Common.BaseDisposable, Eas.WebCrawler.Interfaces.CompletedRequestHistory{
        private Eas.WebCrawler.Interfaces.WebCrawlerContext _Context;
        private System.IO.TextWriter _Writer;
        private string _FileName;
        private object _Lock;

        /// <summary>Disposes of this object, shouldbe implemented in derived classes with resources.</summary>
        /// <param name="isDisposing">Whether or not the class is being explicitly disposed (<code>true</code>) or finalized (<code>false</code>).</param>
        protected override void Dispose(bool isDisposing) {
            try {
                if (isDisposing) {
                    Clear();
                }
            }finally{
                base.Dispose(isDisposing);
            }
        }

        private void Clear() {
            lock (_Lock) {
                if (_Writer != null) {
                    _Writer.Dispose();
                    _Writer.Close();
                    _Writer = null;
                }
            }
        }

        /// <summary>Creates a <see cref="FileBasedRequestHistory"/> from the full name of file where completed request Uris will be stored.</summary>
        /// <param name="fileName"></param>
        public FileBasedRequestHistory(string fileName) {
            _Lock = new object();
            _FileName = fileName;
        }

        #region CompletedRequestHistory Members

        /// <summary>Returns an enumeration of all the Uris in the completed-requests file which this class wraps.</summary>
        /// <returns>An enumeration of all the Uris in the completed-requests file which this class wraps.</returns>
        public IEnumerable<Uri> GetCompletedRequests() {
            if (System.IO.File.Exists(_FileName)) {
                using (System.IO.StreamReader reader = new System.IO.StreamReader(_FileName)) {
                    string line = reader.ReadLine();
                    while (line != null) {
                        if ((!string.IsNullOrEmpty(line)) && (!line.StartsWith("//"))) {
                            Uri uri = null;
                            Uri.TryCreate(line, UriKind.RelativeOrAbsolute, out uri);
                            if (uri != null)
                                yield return uri;
                        }
                        line = reader.ReadLine();
                    }
                }
            }
        }

        /// <summary>Adds a Uri to the file of completed requests.</summary>
        /// <param name="uri">The uri to add.</param>
        public void AddCompletedRequest(Uri uri) {
            Writer.WriteLine(uri.ToString());
        }

        #endregion

        #region WebCrawlerComponent Members

        /// <summary>Initializes this class</summary>
        /// <param name="context">The <see cref="Eas.WebCrawler.Interfaces.WebCrawlerContext"/> which will contain data about this instance of the web crawler.</param>
        public void Initialize(Eas.WebCrawler.Interfaces.WebCrawlerContext context) {
            _Context=context;
            _Context.Events.Stopped+=new EventHandler(Stop);
        }

        #endregion

        private void Stop(object sender, System.EventArgs args) {
            Clear();
        }

        private System.IO.TextWriter Writer {
            get {
                if (_Writer == null) {
                    lock (_Lock) {
                        if (_Writer==null) {
                            _Writer = new System.IO.StreamWriter(_FileName, true);
                        }
                    }
                }
                return _Writer;
            }
        }
    }
}
